package gui.mapper;

import gui.Main.GUI;
import gui.menus.NodeOptions;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.HashSet;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;

import cs340.stormtroopers.hypeerweb.Node;

/**
 * Gui component for listing nodes in a HyperPeerWeb
 * 
 * @author Matthew Smith
 * 
 */
public class NodeListing extends JPanel
{

	private static final long serialVersionUID = -2076848801761499132L;

	/* Root of the GUI */
	private GUI main;

	/* Container for the List Panel */
	private JScrollPane listPane;

	/* JList of nodes */
	private JList nodeList;

	/* List model used to manipulate the list */
	private DefaultListModel nodeListModel;

	/** When pushed it removes all nodes except an initial 0 node. */
	private JButton clearButton;

	public static final int MAX_NUMBER_OF_NODES = 128;
	/**
	 * Creates and intializes a Node Listing
	 * 
	 * @param main
	 */
	public NodeListing(GUI main)
	{
		this.main = main;

		init();

		initList();
	}
	
	/**
	 * Initializes GUI components
	 */
	public void init()
	{
		this.setLayout(new BorderLayout());

		nodeListModel = new DefaultListModel();

		nodeList = new JList(nodeListModel);
		nodeList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
		nodeList.setCellRenderer(new NodeCellRenderer(main));
		nodeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		nodeList.addMouseListener(new PopupListener(new NodeOptions(main)));

		listPane = new JScrollPane(nodeList);

		// Build the clear button
		clearButton = new JButton("Clear");
		clearButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				clearButtonPressed();
			}
		});
		clearButton.setMnemonic(KeyEvent.VK_K);
		add(listPane, BorderLayout.CENTER);
		add(clearButton, BorderLayout.SOUTH);
	}

	public int getSelectedIndex()
	{
		return nodeList.getSelectedIndex();
	}
	
	public String getValueAtSelectedIndex()
	{
		return nodeListModel.get(nodeList.getSelectedIndex()).toString();
	}

	/**
	 * updates the list of components used by the node list
	 */
	public void initList()
	{
		HashMap<Integer, Node> nodes = main.getHyPeerWeb().getNodeMap();

		for (int i = 0; i < MAX_NUMBER_OF_NODES; i++)
		{

			if (nodes.get(i) == null)
			{
				nodeListModel.addElement("");
			}
			else
			{
				nodeListModel.addElement(Integer.toString(i));
			}
		}
	}

	public void addWebIdValueToList(int webIdValue)
	{
		nodeListModel.set(webIdValue, Integer.toString(webIdValue));
	}
	
	public void removeWebIdValue(int webIdValue)
	{
		nodeListModel.set(webIdValue, "");
		nodeList.clearSelection();
	}
	
	public void clearList()
	{
		nodeListModel.clear();
	}

	private void clearButtonPressed()
	{
		nodeList.clearSelection();
		/*
		main.getHyPeerWeb().clear();
//		clearList();
		main.getHyPeerWeb().addAnotherNode();
		initList();
		*/
		main.getHyPeerWebDebugger().getTracePanel().println("Clear Button not implemented in distributed system");
	}

	/**
	 * Helper class for displaying the popup menu on a selected object
	 * 
	 * You may want to design the popup menu listener work better with your
	 * implementation
	 * 
	 * @author Matthew Smith
	 * 
	 */
	private class PopupListener extends MouseAdapter
	{

		JPopupMenu cellOptions;

		public PopupListener(JPopupMenu cellOptions)
		{
			this.cellOptions = cellOptions;
		}

		public void mousePressed(MouseEvent e)
		{
			maybeShowPopup(e);
		}

		public void mouseReleased(MouseEvent e)
		{
			maybeShowPopup(e);
		}

		private void maybeShowPopup(MouseEvent e)
		{
			int index = nodeList.locationToIndex(e.getPoint());
			if (e.isPopupTrigger())
			{

				// A right click won't set the selectedIndex but this routing
				// will be called,
				// so this sets the index.
				nodeList.setSelectedIndex(nodeList.locationToIndex(e.getPoint()));

				cellOptions.show(e.getComponent(), e.getX(), e.getY());
			}
		}
	}

}
